/*
\ brief:  实现文件
\ author: 清晨与猫鱼
*/
#include <iostream>
#include <memory>
#include <list>
#include <algorithm>        // 算法库

using namespace std;

/*
\ brief:   定义一个人类对象
\ author: 清晨与猫鱼
*/
class Person {
public:
    explicit Person(string name, string gender, string maritalStatus)
        : name_(move(name)), 
        gender_(move(gender)),
        maritalStatus_(move(maritalStatus)){        
    }

    string& getName() {
        return name_;
    }

    string&  getGender() {
        return gender_;
    }

    string& getMaritalStatus() {
        return maritalStatus_;
    }
private:
    string name_;
    string gender_;
    string maritalStatus_;
};


/*
\ brief:  抽象接口类
\ author: 清晨与猫鱼
*/
class Criteria {
public:
    virtual list<Person>* meetCriteria(list<Person>& persons) = 0;      // 虚函数接口：满足标准
};


/*
\ brief:  标准的男性
\ author: 清晨与猫鱼
*/
class CriteriaMale 
    : public Criteria {
public:

/*
\ brief:  返回满足标准的人类
\ author: 清晨与猫鱼
*/
    list<Person>* meetCriteria(list<Person>& persons) {
        // 先创建一个容器
        list<Person>* malePersons  = new list<Person>;

        // 将满足标准的人添加到容器中
        for (Person& person: persons) {
            if (person.getGender() == "Male") {
                malePersons->push_back(person);
            }
        }
        return malePersons;
    }
};



/*
\ brief:   标准的女性
\ author: 清晨与猫鱼
*/
class CriteriaFemale 
    : public Criteria{
public:
    list<Person>* meetCriteria(list<Person>& persons) {
        list<Person>* malePersons  = new list<Person>;
        for (Person& person: persons) {
            if (person.getGender() == "Female") {
                malePersons->push_back(person);
            }
        }
        return malePersons;
    }

};


/*
\ brief:  标准单身的
\ author: 清晨与猫鱼
*/
class CriteriaSingle  
    : public Criteria{
public:
    list<Person>* meetCriteria(list<Person>& persons) {
        list<Person>* malePersons  = new list<Person>;
        for (Person& person: persons) {
            if (person.getMaritalStatus() == "Single") {
                malePersons->push_back(person);
            }
        }
        return malePersons;
    }

};



/*
\ brief:  同时满足两种标准的
\ author: 清晨与猫鱼
*/
class AndCriteria 
    : public Criteria {
public:
    explicit AndCriteria(Criteria* criteria, Criteria* otherCriteria)
        : criteria_(criteria), otherCriteria_(otherCriteria) {            
    }

    list<Person>* meetCriteria(list<Person>& persons) {       
        unique_ptr<list<Person>> firstCriteriaPersons(criteria_->meetCriteria(persons));
        return otherCriteria_->meetCriteria(*firstCriteriaPersons);
    }

private:
    unique_ptr<Criteria> criteria_; 
    unique_ptr<Criteria> otherCriteria_;
};




/*
\ brief:  满足其中一种标准的
\ author: 清晨与猫鱼
*/
class OrCriteria 
    : public Criteria {
public:
    explicit OrCriteria(Criteria* criteria, Criteria* otherCriteria)
        : criteria_(criteria), otherCriteria_(otherCriteria) {            
    }

    list<Person>* meetCriteria(list<Person>& persons) {       
        list<Person>* firstCriteriaItems = criteria_->meetCriteria(persons);
        unique_ptr<list<Person>> otherCriteriaItems(otherCriteria_->meetCriteria(persons));

        for (Person& person : *otherCriteriaItems) {
           auto it = find_if(firstCriteriaItems->begin(), firstCriteriaItems->end(),[&](Person& pe){
                        return pe.getName() == person.getName();
                    });

            if (it == firstCriteriaItems->end()) {
                firstCriteriaItems->push_back(person);
            }
        }

        return firstCriteriaItems;
    }
private:
    unique_ptr<Criteria> criteria_; 
    unique_ptr<Criteria> otherCriteria_;
};






